import { Server as SocketIOServer, Socket } from 'socket.io';
import { Server as HTTPServer } from 'http';
import { verify } from 'jsonwebtoken';
import { findUserById } from '../models/User';

// 扩展Socket接口以包含用户信息
interface AuthenticatedSocket extends Socket {
  userId?: number;
  username?: string;
}

// 创建Socket.IO服务器
export const createSocketServer = (httpServer: HTTPServer): SocketIOServer => {
  const io = new SocketIOServer(httpServer, {
    cors: {
      origin: process.env.CLIENT_URL || 'http://localhost:3000',
      methods: ['GET', 'POST']
    }
  });

  // 身份验证中间件
  io.use(async (socket: AuthenticatedSocket, next) => {
    try {
      const token = socket.handshake.auth.token;
      
      if (!token) {
        return next(new Error('认证失败：缺少令牌'));
      }
      
      const jwtSecret = process.env.JWT_SECRET;
      if (!jwtSecret) {
        return next(new Error('服务器配置错误'));
      }
      
      // 验证令牌
      const decoded = verify(token, jwtSecret) as { id: number };
      
      // 获取用户信息
      const user = await findUserById(decoded.id);
      if (!user) {
        return next(new Error('认证失败：用户不存在'));
      }
      
      // 将用户信息添加到socket
      socket.userId = user.id;
      socket.username = user.username;
      
      next();
    } catch (error) {
      next(new Error('认证失败：无效令牌'));
    }
  });

  // 连接处理
  io.on('connection', (socket: AuthenticatedSocket) => {
    console.log(`用户 ${socket.username} (ID: ${socket.userId}) 已连接`);
    
    // 加入用户个人房间
    socket.join(`user:${socket.userId}`);
    
    // 处理加入游戏房间
    socket.on('join-game', (gameId: string) => {
      socket.join(`game:${gameId}`);
      console.log(`用户 ${socket.username} 加入游戏房间 ${gameId}`);
      
      // 通知房间内其他用户
      socket.to(`game:${gameId}`).emit('user-joined', {
        userId: socket.userId,
        username: socket.username
      });
    });
    
    // 处理离开游戏房间
    socket.on('leave-game', (gameId: string) => {
      socket.leave(`game:${gameId}`);
      console.log(`用户 ${socket.username} 离开游戏房间 ${gameId}`);
      
      // 通知房间内其他用户
      socket.to(`game:${gameId}`).emit('user-left', {
        userId: socket.userId,
        username: socket.username
      });
    });
    
    // 处理游戏动作
    socket.on('game-action', (data: { gameId: string; action: string; payload: any }) => {
      const { gameId, action, payload } = data;
      
      // 广播游戏动作到房间内其他用户
      socket.to(`game:${gameId}`).emit('game-action', {
        userId: socket.userId,
        username: socket.username,
        action,
        payload
      });
    });
    
    // 处理聊天消息
    socket.on('chat-message', (data: { gameId: string; message: string }) => {
      const { gameId, message } = data;
      
      // 广播聊天消息到游戏房间内所有用户
      io.to(`game:${gameId}`).emit('chat-message', {
        userId: socket.userId,
        username: socket.username,
        message,
        timestamp: new Date()
      });
    });
    
    // 处理断开连接
    socket.on('disconnect', () => {
      console.log(`用户 ${socket.username} (ID: ${socket.userId}) 已断开连接`);
      
      // 通知所有相关游戏房间
      const rooms = Array.from(socket.rooms);
      rooms.forEach(room => {
        if (room.startsWith('game:')) {
          socket.to(room).emit('user-disconnected', {
            userId: socket.userId,
            username: socket.username
          });
        }
      });
    });
  });

  return io;
};